package cn.shop.admin.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.shop.admin.service.FrontUserService;
import cn.shop.admin.service.FundDetailService;
import cn.shop.admin.service.OrderRewardService;
import cn.shop.transcation.order.entity.OrderReward;
import cn.shop.transcation.order.entity.OrderRewardQueryReq;
import cn.shop.transcation.order.mapper.OrderRewardMapper;
import cn.shop.transcation.promotionsModule.Promotions;
import cn.shop.transcation.promotionsModule.mapper.PrizeRuleMapper;
import cn.shop.transcation.withdraw.entity.Withdraw;
import cn.shop.utils.PageUtil;
import cn.shop.utils.constant.PromotionsConstant;
import cn.shop.utils.exception.ServiceException;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class OrderRewardServiceImpl extends ServiceImpl<OrderRewardMapper, OrderReward> implements OrderRewardService {

    @Resource
    private FrontUserService frontUserService;
    @Resource
    private FundDetailService fundDetailService;
    @Resource
    private PrizeRuleMapper prizeRuleMapper;
    @Resource
    private PromotionsServiceImpl promotionsService;

    @Override
    public Map<String, Object> listPage(OrderRewardQueryReq req) {
        Page<OrderReward> page = Page.of(req.getCurrent(), req.getSize());
        page = baseMapper.pageWithOrderReward(page, req);
        return PageUtil.formatPage(page, null);
    }

    @Override
    public Map<String, Object> statistics(OrderRewardQueryReq req) {
        return baseMapper.statistics(req);
    }

    @Override
    public List<OrderReward> queryReward(List<Integer> types) {
        return baseMapper.queryReward(types);
    }

    @Override
    @Transactional
    public void unreward(Withdraw withdraw) {
        OrderReward reward = lambdaQuery()
                .eq(OrderReward::getOrderId, withdraw.getId())
                .oneOpt().orElse(null);
        if (reward == null) {
            return;
        }
        boolean isSuccess = promotionsService.update(Wrappers.<Promotions>lambdaUpdate()
                .setSql("prize_pool = prize_pool ++ " + reward.getAmount())
                .eq(Promotions::getKey, PromotionsConstant.APP_REWARD)
                .gt(Promotions::getPrizePool, BigDecimal.ZERO));
        if (!isSuccess) {
            throw new ServiceException("删除奖励操作失败");
        }
    }

    private BigDecimal calculationReward(Withdraw record, BigDecimal reward) {
        boolean isSuccess = promotionsService.update(Wrappers.<Promotions>lambdaUpdate()
                .setSql("prize_pool = prize_pool - " + reward)
                .eq(Promotions::getKey, PromotionsConstant.APP_REWARD)
                .gt(Promotions::getPrizePool, BigDecimal.ZERO));
        BigDecimal actualReward = BigDecimal.ZERO;
        if (isSuccess) {
            //扣款成功
            //如果扣款完是负数
            //则不给奖励
            //如果扣款完负数比奖励低，则把剩余的给了
            //不是负数则正常给
            Promotions promotions = promotionsService.getOne(Wrappers.<Promotions>lambdaQuery()
                    .eq(Promotions::getKey, PromotionsConstant.APP_REWARD));
            if (promotions == null) {
                return actualReward;
            }
            if (NumberUtil.isLess(promotions.getPrizePool(), BigDecimal.ZERO)) { //奖池金额小于0
                if (!NumberUtil.isLess(promotions.getPrizePool().abs(), reward)) { //奖池剩余金额的绝对值小于手续费，需要补回奖池里的金额
                    actualReward = reward.subtract(promotions.getPrizePool().abs());
                    log.info("用户{} 提现{} 实际到账金额{}，从活动奖池奖励{}，奖池剩余不足{}，实际奖励{}",
                            record.getUserId(), record.getAmount(), record.getActualAmount(), reward, promotions.getPrizePool(), actualReward);
                }
            } else {
                log.info("用户{} 提现{} 实际到账金额{}，从活动奖池中补回手续费{}，奖池剩余{}",
                        record.getUserId(), record.getAmount(), record.getActualAmount(), reward, promotions.getPrizePool());
                actualReward = reward;
            }
        }
        return actualReward;
    }
}
